home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 7
/
BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso
/
Files
/
DA
/
P
/
PCalculator.cpt
/
CalcDA sources
/
CalcDA_Arithmetic.c
next >
Wrap
Text File
|
1990-07-06
|
6KB
|
315 lines
/*
* CalcDA_Arithmetic.c for the Programmer's Calculator project
*
* Copyright 1990, Peter Ohler
*
* All Rights Reserved
*
* The Programmer's Calculator and the source code are shareware. That means
* they are not free. If you use either the source or the calculator then
* send $5 or $10 (whatever you feel its worth) to the address that follows.
* The source and calculator can be distributed for free. Prior to any sale
* of either the source code or the calculator my permission must be
* obtained. This includes sales by shareware distribution houses that sell
* shareware.
*
* Peter Ohler
*
* 3184 Rohrer Drive, Lafayette CA 94549
*
* (415) 284-7828
*
* ***************************************************************************
*
* Contains the functions that need two arguments and expect the function
* designator (*, /, +, -, ...) to be selected between the two arguments.
* Functions are placed on a stack so that the highest precedence operation
* is executed first. For example if the sequence: 2 + 3 * 4 is entered it
* will be evaluated as 2 + (3 * 4) as convention suggests. It would not be
* evaluated in the order entered or as (2 + 3) * 4.
*/
#include "CalcDA.h"
/*
* ***************************************************************************
* prototypes
*/
extern void UpdateXRegText(void);
extern void UpdateReg2Text(void);
extern IntFunc PopFuncStack(void);
extern int PushFuncStack(IntFunc func);
extern void PopYReg(void);
extern int PushXonYReg(void);
extern void FreezeXReg(void);
extern double Power(double x, double y);
int ChangeSign(void);
int EvalOrder(IntFunc func);
int DoArithmetic(IntFunc func);
int DoEqual(void);
int DoOr(void);
int DoAnd(void);
int DoXor(void);
int DoShiftRight(void);
int DoShiftLeft(void);
int DoPlus(void);
int DoMinus(void);
int DoMultiply(void);
int DoDivide(void);
int DoModulo(void);
int DoPower(void);
int DoInvPower(void);
/*
* ***************************************************************************
* variables
*/
extern int exponentActive;
extern int exponent;
/*
* ***************************************************************************
* functions
*/
/*
* Ok, ok, so this function only takes one argument. For all the operations
* functions in this file the x register is updated after the x value is
* changed.
*/
int
ChangeSign()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv *= -1;
} else {
if (exponentActive)
exponent = -exponent;
else
xReg.value.dv *= -1.0;
}
UpdateXRegText();
return 0;
}
/*
* This functions returns the evaluation precedence of a function. Not real
* elegant but effective.
*/
int
EvalOrder(func)
IntFunc func;
{
if (func == DoEqual)
return 0;
if (func == DoOr || func == DoAnd || func == DoXor)
return 1;
if (func == DoShiftRight || func == DoShiftLeft)
return 2;
if (func == DoPlus || func == DoMinus)
return 3;
if (func == DoMultiply || func == DoDivide || func == DoModulo)
return 4;
if (func == DoPower || func == DoInvPower)
return 5;
return -1;
}
/*
* The actual evaluation of the operations entered is done by this function.
* It will execute any pending operations that have a higher precedence
* before putting the func on the operations stack (funcPending). The y
* register is really a stack for the x values that have been pushed on,
* awaiting an operation.
*/
int
DoArithmetic(func)
IntFunc func;
{
IntFunc topFunc;
int order;
int ok = 0;
order = EvalOrder(func);
while (EvalOrder(*funcPending) >= order) {
if (0L == (topFunc = PopFuncStack()) || (*topFunc)()) {
SysBeep(1);
} else {
/*
* Assume that the x and y registers were used and
* the results was put in the x register. The y
* register is no longer needed and the value should
* be popped off.
*/
PopYReg();
}
}
if (order > 0) {
if (PushXonYReg() || PushFuncStack(func))
ok == -1;
}
FreezeXReg();
UpdateReg2Text();
return ok;
}
/*
* The equal function doesn't have to do anything. It is only used to force
* all pending operations to be executed.
*/
int
DoEqual()
{
return 0;
}
/*
* Most of the rest of the functions are similar. Each peforms some
* operation on the x and y value and leaves the result in the x register.
*/
int
DoPlus()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv += (*yReg).value.lv;
} else {
xReg.value.dv += (*yReg).value.dv;
}
return 0;
}
int
DoMinus()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv = (*yReg).value.lv - xReg.value.lv;
} else {
xReg.value.dv = (*yReg).value.dv - xReg.value.dv;
}
return 0;
}
int
DoMultiply()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv *= (*yReg).value.lv;
} else {
xReg.value.dv *= (*yReg).value.dv;
}
return 0;
}
int
DoModulo()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv = (*yReg).value.lv % xReg.value.lv;
} else {
return -1;
}
return 0;
}
int
DoDivide()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv = (*yReg).value.lv / xReg.value.lv;
} else {
xReg.value.dv = (*yReg).value.dv / xReg.value.dv;
}
return 0;
}
int
DoOr()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv |= (*yReg).value.lv;
} else {
return -1;
}
return 0;
}
int
DoAnd()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv &= (*yReg).value.lv;
} else {
return -1;
}
return 0;
}
int
DoXor()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv ^= (*yReg).value.lv;
} else {
return -1;
}
return 0;
}
int
DoShiftRight()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv = (*yReg).value.lv >> xReg.value.lv;
} else {
return -1;
}
return 0;
}
int
DoShiftLeft()
{
if (INTEGER == typeStack.pos) {
xReg.value.lv = (*yReg).value.lv << xReg.value.lv;
} else {
return -1;
}
return 0;
}
int
DoPower()
{
double x;
if (INTEGER == typeStack.pos) {
x = Power((double)(*yReg).value.lv, (double)xReg.value.lv);
if (SIGNED == signStack.pos)
xReg.value.lv = (long)x;
else
xReg.value.lv = (uLong)x;
} else {
xReg.value.dv = Power((*yReg).value.dv, xReg.value.dv);
}
return 0;
}
int
DoInvPower()
{
double x;
if (INTEGER == typeStack.pos) {
x = Power((double)(*yReg).value.lv, 1.0 / (double)xReg.value.lv);
if (SIGNED == signStack.pos)
xReg.value.lv = (long)x;
else
xReg.value.lv = (uLong)x;
} else {
xReg.value.dv = Power((*yReg).value.dv, 1.0 / xReg.value.dv);
}
return 0;
}